package pkg

import (
	"fmt"
	"operator-crd/pkg/generated/clientset/versioned"
	informerv1 "operator-crd/pkg/generated/informers/externalversions/bseip.baison.net/v1"
	listerv1 "operator-crd/pkg/generated/listers/bseip.baison.net/v1"
	"reflect"
	"time"

	"k8s.io/apimachinery/pkg/util/runtime"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/client-go/tools/cache"
	"k8s.io/client-go/util/workqueue"
)

type controller struct {
	client   versioned.Clientset
	ckLister listerv1.ClickHouseLister
	queue    workqueue.RateLimitingInterface
}

func NewController(client versioned.Clientset, ckInformer informerv1.ClickHouseInformer) controller {
	ctr := controller{
		client:   client,
		ckLister: ckInformer.Lister(),
		queue:    workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "ckManager"),
	}

	ckInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
		AddFunc:    ctr.add,
		UpdateFunc: ctr.update,
		DeleteFunc: ctr.del,
	})
	return ctr
}

func (ctr *controller) Run(stopCh chan struct{}) {
	for i := 0; i < 5; i++ {
		go wait.Until(ctr.worker, time.Minute, stopCh)
	}
	<-stopCh
}

func (ctr *controller) add(obj interface{}) {
	ctr.enqueue(obj)
	fmt.Println("新增了一个ck！")
}

func (ctr *controller) update(oldObj interface{}, newObj interface{}) {
	if reflect.DeepEqual(oldObj, newObj) {
		return
	}
	ctr.enqueue(newObj)
	fmt.Println("更新了一个ck！")
}

func (ctr *controller) del(obj interface{}) {
	ctr.enqueue(obj)
	fmt.Println("删除了一个ck！")
}

func (ctr *controller) enqueue(obj interface{}) {
	key, err := cache.MetaNamespaceKeyFunc(obj)
	if err != nil {
		runtime.HandleError(err)
	}
	ctr.queue.Add(key)
}

func (ctr *controller) worker() {
	for ctr.processNextItem() {
	}
}

func (ctr *controller) processNextItem() bool {
	item, shutdown := ctr.queue.Get()
	if shutdown {
		return false
	}
	defer ctr.queue.Done(item)
	key := item.(string)
	err := ctr.doCk(key)
	if err != nil {
		ctr.handlerError(key, err)
	}
	return true
}

func (ctr *controller) handlerError(key string, err error) {
	for ctr.queue.NumRequeues(key) <= 10 {
		ctr.queue.AddRateLimited(key)
		return
	}
	runtime.HandleError(err)
	ctr.queue.Forget(key)
}

func (ctr *controller) doCk(key string) error {
	namespaceKey, name, err := cache.SplitMetaNamespaceKey(key)
	if err != nil {
		return err
	}
	//处理逻辑
	fmt.Println(namespaceKey, name)
	return nil
}
